home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / mus / midi / XGToolset5_src.lha / XGToolset_src / HowtoProgramSysEx.doc < prev    next >
Text File  |  1999-03-22  |  6KB  |  290 lines

  1. How to programm SYSEX in Bars&Pipes Tools
  2.  
  3. by Alfred Faust j.k.dax@tonline.de
  4.  
  5.  
  6. First: I'm a german man, and I am not so good in the english language
  7.  
  8. In the "Rules for Tools" manual I found the sentence:
  9.  
  10. (In the capture :"Events, Clips, & Tracks  - Events - 'type'")
  11.  
  12. "... Only 'EVENT_VOICE' Events flow through the PipeLine; therefore Tools need
  13. only concern themselves with this one type. ... "
  14.  
  15. That isn't right. 'EVENT_SYSX' Events are also flows through the Pipeline. I
  16. found out how to handle this events, sending directly through the PipeLine and
  17. writing them in the track.
  18.  
  19. Here is the result of my (guess)work.
  20.  
  21. First make a string that hold the sysex:
  22.  
  23. {
  24.     char *sysex;
  25.     ...
  26.  
  27.     sysex = "F07E7F0901F7";  //this is the Geral-MIDI Reset
  28.  
  29.     ...
  30.  
  31. }
  32.  
  33. or:
  34.  
  35. {
  36.     char *sysex;
  37.     storage[16];
  38.  
  39.     ...
  40.  
  41.     sprintf(storage, "F07E7F0901F7");
  42.     sysex = storage;
  43.  
  44.     ...
  45.  
  46. }
  47.  
  48. ( It is very important that you ALWAYS use STRINGS (char) - not int- or
  49. BYTE-values. You must ALWAYS translate (int or BYTE)-values into (char).
  50.  
  51. Have a look at the source-codes of my XGTools. There you can also see, how to
  52. put a prop-gadget-value in the SysExString.
  53.  
  54. One possibility:
  55.  
  56. {
  57.     char *sysex;
  58.     storage[16];
  59.     int value = 2;
  60.     // this can be the value of a slider
  61.  
  62.     char hexstr[3][2]={"00","01","02"};
  63.     //that are hexvalues !!!
  64.  
  65.     ...
  66.  
  67.     sprintf(storage, "F043104C020102%.2sF7", hexstr[value] );
  68.  
  69.  
  70.  /*
  71.     this is the sysex for REVERB-time in XG-Devices
  72.     The "%.2" will be replaced by "02" from hexstr-array,
  73.     and then written into storage.
  74.  
  75.     You can also write:
  76.  
  77.     sprintf(storage, "F043104C020102%02lxF7", value)
  78.  
  79.     in this case you don't need the "hexstr"
  80.  
  81.     The "%02lx" will replaced by the value. Always a 2 nibble hexbyte will be
  82.     written on this place.
  83.  
  84.     Exapmle:
  85.  
  86.     A value of a slider(Prop-Gadget) is given as decimal "20".
  87.     %02lx will be replaced by "14" as hexbyte.
  88.  */
  89.     sysex = storage;
  90.  
  91.     ... )
  92.  
  93. For my routines it MUST be a string. Then put it on the way.
  94.  
  95. These are all functions you need:
  96.  
  97. //the clip-routines for writing in the track
  98.  
  99. static BOOL lock_clip(struct Clip *clip) {
  100.   Forbid();
  101.   if (clip->locked == 0)
  102.     {
  103.       clip->locked = 1;
  104.       Permit();
  105.       return TRUE;
  106.     }
  107.   else
  108.     {
  109.       Permit();
  110.       return FALSE;
  111.     } }
  112.  
  113. static void unlock_clip(struct Clip *clip) {
  114.   clip->locked = 0; }
  115.  
  116. //writes sysex into track
  117.  
  118. static void insertsysex(char *buff, short size,
  119.              struct MNXGTool *tool,const LONG time) {
  120.  struct StringEvent *event;
  121.  struct String *string;
  122.  
  123.  event = (struct StringEvent *) (*functions->allocevent)();
  124.  if (event)
  125.  {
  126.   string = (struct String *) (*functions->myalloc)(size + 3, MEMF_CLEAR);
  127.   if (string)
  128.   {
  129.    event->next = NULL;
  130.    event->string = string;
  131.    memcpy(string->string,  buff,  size);
  132.    string->length = size + 2;
  133.    event->type = EVENT_SYSX;
  134.    event->status = MIDI_SYSX;
  135.    event->time = time;
  136.    event->tool = tool->tool.next;
  137.    if (lock_clip(&(tool->tool.track->clip)))
  138.    {
  139.     event->next =
  140.     (struct StringEvent *)tool->tool.track->clip.events.first;
  141.  
  142.     tool->tool.track->clip.events.first =
  143.     (struct Event *)(*functions->sorteventlist)(event);
  144.  
  145.     unlock_clip(&(tool->tool.track->clip));
  146.    }
  147.    else
  148.    {
  149.     (*functions->freelist)(event);
  150.    }
  151.   }
  152.  } }
  153.  
  154. // the routine for sending SysEx-data thru the pipeline
  155.  
  156. static void sendsysex(char *buff, short size,
  157.             struct MNXGTool *tool, const LONG time) {
  158.  struct StringEvent *event;
  159.  struct String *string;
  160.  
  161.  event = (struct StringEvent *) (*functions->allocevent)();
  162.   if (event)
  163.   {
  164.    string = (struct String *) (*functions->myalloc)(size + 3, MEMF_CLEAR);
  165.    if (string)
  166.    {
  167.     event->string = string;
  168.     memcpy(string->string,  buff,  size);
  169.     string->length = size + 2;
  170.     event->type = EVENT_SYSX;
  171.     event->status = MIDI_SYSX;
  172.     event->time = time;
  173.     event->tool = tool->tool.next;
  174.     WaitTOF();
  175.     (*functions->qevent)(event);
  176.     (*functions->myfree)(string);
  177.    }
  178.   } }
  179.  
  180. // THE MOST IMPORTANT TRANSLATION-ROUTINE
  181.  
  182. static void  trans_hx(struct MNXGTool *tool,
  183.             const LONG time, char *sysx, int sw) {
  184.   LONG size;
  185.   int a,  b,  x,  y ;
  186.   UBYTE abuf[32];
  187.   char chr[4];
  188.   char *zbuf = NULL;
  189.   struct Event *sysx_event;
  190.  
  191. /*
  192.    translate sysexbuffer (there are single chars, with his own hexvalue)
  193.    into hex (always two chars to one hexvalue)
  194.  
  195.    example: "F0"
  196.    In the string there are two hexvalues :
  197.    0x46 for "F" in the ASCII-table
  198.    0x30 for "0" in the ASCII-table
  199.    But we will send the hex-value "0xF0" AND NOT "0x46 0x30"
  200.    so we must translate ... */
  201.  
  202.  
  203. size = strlen(sysx); zbuf = (char *)AllocVec(size+2,  MEMF_ANY|MEMF_CLEAR);
  204. if(zbuf)
  205.  {
  206.   CopyMem(sysx,  zbuf,  size);
  207.   b=0;
  208.   for(a=0;a < size;a=a+2)
  209.   {
  210.    chr[0] = zbuf[a];
  211.    chr[1] = zbuf[a+1];
  212.  
  213.    x=(isdigit((int)chr[0]))? (chr[0]&0xF) : ((chr[0]&0xDF)-55);
  214.    y=(isdigit((int)chr[1]))? (chr[1]&0xF) : ((chr[1]&0xDF)-55);
  215.    //this is the translationscore - don't touch !!!
  216.  
  217.    abuf[b++] = ((x<<4)|y);
  218.    //writing with bitmanipulation
  219.  
  220.    }
  221.  
  222.   FreeVec(zbuf);
  223.  
  224.   if (sw == 0) sendsysex(abuf,  b,  tool,  time);
  225.   if (sw == 1) insertsysex(abuf,  b,  tool,  time);
  226.   //put hexdata away
  227.  
  228.  } }
  229.  
  230.  
  231. There are now to possibilities.
  232.  
  233. 1. Sending through the PipeLine:
  234.  
  235.  
  236. {
  237.     struct my_Tool *tool;
  238.     // a pointer to your Tool-structure
  239.  
  240.     char *sysex;
  241.     ...
  242.  
  243.     sysex = "F07E7F0901F7";
  244.     //this is the Geral-MIDI Reset
  245.  
  246.  
  247.     trans_hx(tool, functions->timenow, sysex, 0)
  248.     // "0" =  switch for sending
  249.     ...
  250.  
  251. }
  252.  
  253. If you only need the sendsysex-routine the clip-routines are here not
  254. necessary.
  255.  
  256.  
  257. 2. Writing in the Track:
  258.  
  259. {
  260.   struct my_Tool *tool;
  261.   // a pointer to your Tool-structure
  262.  
  263.   char *sysex;
  264.  
  265.   ...
  266.  
  267.   sysex = "F07E7F0901F7";  //this is the Geral-MIDI Reset
  268.  
  269. if ((*functions->areyousure)("write to track ? Play-pointer on right place?"))
  270.       //this is a nice question ...
  271.  
  272.    {
  273.    if (!functions->running)
  274.        // You CAN'T write into track, if the sequencer is running !!!
  275.  
  276.      {
  277.    trans_hx(tool, functions->starttime, sysex, 1)
  278.    // "1" = switch for writing
  279.  
  280.      }
  281.    }
  282.  
  283.   ...
  284.  
  285. }
  286.  
  287. If you don't need my comments - kill them ...
  288.  
  289. I hope my pain, sweat and many sleepless nights are not only useful for  my own.
  290.